package edu.kit.csl.cratylus.extraction.elki;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.regex.Pattern;

import de.lmu.ifi.dbs.elki.data.type.SimpleTypeInformation;
import de.lmu.ifi.dbs.elki.datasource.bundle.BundleMeta;
import de.lmu.ifi.dbs.elki.datasource.parser.AbstractStreamingParser;
import de.lmu.ifi.dbs.elki.logging.Logging;
import edu.kit.csl.cratylus.datatypes.Candidate;
import edu.kit.csl.cratylus.datatypes.Word;

/**
 * Reads a line separated candidate list from a file and converts it into ELKI
 * suitable data structures. This class is only used when the project is 
 * started with the GUI of ELKI for visualization purposes of phoneme sequence
 * clustering experiments.
 */
public class PlainWordParser extends AbstractStreamingParser {

	private static final Logging LOG = Logging.getLogger(PlainWordParser.class);
	protected BufferedReader reader;
	protected BundleMeta meta;
	protected Event nextevent = null;
	protected ElkiCandidate curval;
	
	/**
	 * Sole constructor. Calls the super class constructor.
	 * 
	 * @param colSep not used
	 * @param quoteChar not used
	 * @see de.lmu.ifi.dbs.elki.datasource.parser.AbstractStreamingParser
	 */
	public PlainWordParser(Pattern colSep, char quoteChar) {
		super(colSep, quoteChar);
	}

	/**
	 * Initializes the input stream and the meta data. The meta data contains 
	 * one column for the ElkiCandidate type restriction. Furthermore, this 
	 * constructor initializes the BufferedReader instances with the given
	 * input stream.
	 * 
	 * @param in input stream to tread
	 * @throws NullPointerException if {@code in} is {@code null}
	 */
	@Override
	public void initStream(InputStream in) {
		reader = new BufferedReader(new InputStreamReader(in));
		meta = new BundleMeta(1);
		meta.add(
				new SimpleTypeInformation<ElkiCandidate>(ElkiCandidate.class));
	}

	/**
	 * Get the meta bundle. Returns {@code null} if 
	 * {@link #initStream(InputStream)} was not called before. Otherwise, 
	 * returns the meta bundle created there.
	 * 
	 * @return the meta information
	 * @see #initStream(InputStream)
	 */
	@Override
	public BundleMeta getMeta() {
		return meta;
	}

	/* (non-Javadoc)
	 * @see de.lmu.ifi.dbs.elki.datasource.bundle.BundleStreamSource#data(int)
	 */
	@Override
	public Object data(int rnum) {
		return curval;
	}

	/**
	 * Reads a new line and return {@link Event#NEXT_OBJECT} or returns
	 * {@link Event#END_OF_STREAM}. The read lines are stored as candidates
	 * (trimmed) and returned by {@link #data(int)}.
	 * {@inheritDoc}
	 */
	@Override
	public Event nextEvent() {
		if (nextevent != null) {
			Event ret = nextevent;
			nextevent = null;
			return ret;
		}
		try {
			String line;
			while ((line = reader.readLine()) != null) {
				if (!line.startsWith(COMMENT) && line.length() > 0) {
					String content = line.trim();
					if (content.length() > 0) {
						curval = new ElkiCandidate(new Candidate
								(new Word(content), 0, null));
						return Event.NEXT_OBJECT;
					}
				}
			}
			reader.close();
			reader = null;
			return Event.END_OF_STREAM;
		} catch (IOException e) {
			throw new IllegalArgumentException("Error while parsing");
		}
	}

	/* (non-Javadoc)
	 * @see de.lmu.ifi.dbs.elki.datasource.parser.AbstractParser#getLogger()
	 */
	@Override
	protected Logging getLogger() {
		return LOG;
	}
}
